//
//  HHTagListView.m
//
//  Created by Basic on 15/1/12.
//  Copyright (c) 2015 Basic. All rights reserved.
//

#import "HHTagListView.h"
#import "HHTagButton.h"
#import <BCFoundation/BCFoundationUtils.h>
#import <BCFoundation/UIImage+BCHelper.h>
//#import <BCUIKit/UIButton+BCHelper.h>


@interface HHTagListView ()
/** 是否已经 初始化完成 */
@property (assign, nonatomic) BOOL  didSetup;
/** 选中的按钮 列表 */
@property (nonatomic, strong) NSMutableArray<HHTagButton *> *selectBtns;
/** 按钮 列表 */
@property (nonatomic, strong) NSMutableArray<HHTagButton *> *allBtns;
/** 数据源 */
@property (nonatomic, strong) NSArray<id<HHTagItemProtocol> > *tags;
/** 配置模型，默认配置见 HHTagListConfig.h */
@property (strong, nonatomic, readwrite) HHTagListConfig *config;


@end

@implementation HHTagListView
//MARK: - system
- (instancetype)init
{
    self = [super init];
    if (self) {
        
    }
    return self;
}
- (void)dealloc
{
    BCLogDealloc();
}

//MARK: - Getter Setter
-(HHTagListConfig *)config {
    if (!_config) {
        _config = [[HHTagListConfig alloc] init];
    }
    return _config;
}
- (NSMutableArray<HHTagButton *> *)allBtns {
    if (!_allBtns) {
        _allBtns = [[NSMutableArray<HHTagButton *> alloc] init];
    }
    return _allBtns;
}
-(NSMutableArray *)selectBtns {
    if (!_selectBtns) {
        _selectBtns = [[NSMutableArray<HHTagButton *> alloc] init];
    }
    return _selectBtns;
}
-(NSArray<id<HHTagItemProtocol>> *)selectTags {
    NSMutableArray<id<HHTagItemProtocol>> *selectTags = [[NSMutableArray alloc] init];
    [self.selectBtns enumerateObjectsUsingBlock:^(UIButton * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        if ([obj isKindOfClass:[HHTagButton class]]) {
            HHTagButton *tagBtn = (HHTagButton *)obj;
            [selectTags addObject:tagBtn.tagModel];
        }
    }];
    return selectTags;
}

//MARK: - Event
/**
 每一项的标签按钮点击事件
 
 @param sender sender description
 */
- (void)onItemBtnClick:(HHTagButton *)sender {
    BOOL canClick = YES;
    id<HHTagItemProtocol> tagModel = (id<HHTagItemProtocol> )sender.tagModel;
    if([self.delegate respondsToSelector:@selector(hh_TagListView:shouldSelectTag:)]){
        canClick = [self.delegate hh_TagListView:self shouldSelectTag:tagModel];
    }
    if(!canClick){
        return;
    }
    
    [self onItemBtnClick:sender isGesture:YES];
}
/**
 每一项的标签按钮点击事件
 
 @param sender sender description
 @param isGesture 手势触发
 */
- (void)onItemBtnClick:(HHTagButton *)sender isGesture:(BOOL )isGesture {
    id<HHTagItemProtocol> tagModel = (id<HHTagItemProtocol> )sender.tagModel;
    if (self.config.disableTouchSelect) {
        //如果禁止触摸选中、反选，则直接分发事件
        [self dispatchSelectedEvent:tagModel withCancelTags:nil withGesture:isGesture];
        return ;
    }
    BOOL hasSelected = sender.selected;
    //取消的标签列表
    NSMutableArray *cancelTags = [[NSMutableArray alloc] init];
    if (!self.config.multiSelect && !self.config.selectRepeat && !hasSelected) {
        //单选、不支持反选、上一次状态按钮未选中
        //取消选中其他的
        [self.selectBtns enumerateObjectsUsingBlock:^(UIButton * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            HHTagButton *tagBtn = (HHTagButton *)obj;
            [cancelTags addObject:tagBtn.tagModel];
            [obj setSelected:NO];
        }];
        [self.selectBtns removeAllObjects];
    }
    
    //判断是否可以反选
    if(self.config.selectRepeat){
        //支持反选
        if (!hasSelected) {
            //上一次按钮未选中,去选中
            //先判断当前按钮是否 排斥其他选项
            if (tagModel.exclude) {
                //当前按钮排斥，则取消其他按钮
                [self.selectBtns enumerateObjectsUsingBlock:^(UIButton * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                    HHTagButton *tagBtn = (HHTagButton *)obj;
                    [cancelTags addObject:tagBtn.tagModel];
                    obj.selected = NO;
                }];
                [self.selectBtns removeAllObjects];
            } else {
                //当前按钮不排斥，判断之前已选中的按钮是否排斥
                __block NSMutableArray<HHTagButton *> *delBtns = [[NSMutableArray alloc] init];
                [self.selectBtns enumerateObjectsUsingBlock:^(UIButton * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                    HHTagButton *objBtn = (HHTagButton *)obj;
                    id<HHTagItemProtocol> objBtnModel = (id<HHTagItemProtocol> )objBtn.tagModel;
                    if (objBtnModel.exclude) {
                        //选择的按钮里面有排斥的
                        objBtn.selected = NO;
                        [delBtns addObject:objBtn];
                        [cancelTags addObject:objBtn.tagModel];
                    }
                }];
                if (delBtns.count>0) {
                    [self.selectBtns removeObjectsInArray:delBtns];
                }
            }
            //再选中当前按钮
            [sender setSelected:YES];
            [self.selectBtns addObject:sender];
        }
        else {
            //已选中，取消选中
            [sender setSelected:NO];
            //从已选列表里移除自己
            __block NSInteger  findBtnIndex = -1;
            [self.selectBtns enumerateObjectsUsingBlock:^(UIButton * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                if (obj == sender) {
                    findBtnIndex = idx;
                    HHTagButton *tagBtn = (HHTagButton *)obj;
                    [cancelTags addObject:tagBtn.tagModel];
                    *stop = YES;
                }
            }];
            if (findBtnIndex>=0) {
                [self.selectBtns removeObjectAtIndex:findBtnIndex];
            }
        }
    }
    else {
        //不支持反选
        if(!sender.selected){
            //上一次按钮未选中
            [sender setSelected:YES];
            [self.selectBtns addObject:sender];
        }
        else {
            //之前选中了，不支持反选，就不需要继续分发事件了
            return ;
        }
    }
    //分发事件
    [self dispatchSelectedEvent:tagModel withCancelTags:cancelTags withGesture:isGesture];
}
/// 分发选中事件
- (void)dispatchSelectedEvent:(id<HHTagItemProtocol> )tagModel withCancelTags:(NSArray<id<HHTagItemProtocol>> *_Nullable)cancelTags withGesture:(BOOL )isGesture {
    if ([self.delegate respondsToSelector:@selector(hh_TagListView:didSelectTag:withCancelTags:withGesture:)]) {
        //新的实现
        [self.delegate hh_TagListView:self didSelectTag:tagModel withCancelTags:cancelTags withGesture:isGesture];
    }
}


//MARK: - Private
- (void)layoutTags {
    if (self.didSetup || !self.tags.count) {
        return;
    }
    NSArray *subviews = self.subviews;
    UIView *previousView = nil;
    CGFloat contentTop = self.config.contentPadding.top;
    CGFloat lineTop = self.config.linePadding.top;
    CGFloat lineLeft = self.config.linePadding.left + self.config.contentPadding.left;
    CGFloat lineRight = self.config.linePadding.right + self.config.contentPadding.right;
    CGFloat itemSpacing = self.config.rowSpacing;
    CGFloat lineSpacing = self.config.lineSpacing;
    CGFloat currentX = lineLeft;
    
    if (self.config.maxLine>1 && self.config.maxLayoutWidth > 0) {
        //多行
        NSInteger lineCount = 0;
        for (UIView *view in subviews) {
            if (![view isKindOfClass:[HHTagButton class]]) {
                return;
            }
            HHTagButton *tagBtn = (HHTagButton *)view;
            CGSize size = [HHTagButton intrinsicContentSize:tagBtn.tagModel.name withConfig:self.config];
            //判断是否第一次遍历
            if (previousView) {
                //不是第一次遍历
                CGFloat width = size.width;
                currentX += itemSpacing;
                if (currentX + width + lineRight <= self.config.maxLayoutWidth) {
                    view.frame = CGRectMake(currentX, CGRectGetMinY(previousView.frame), size.width, size.height);
                    currentX += size.width;
                }
                else {
                    //换行
                    if(lineCount>=self.config.maxLine){
                        //行数超过限制
                        break;
                    }
                    lineCount ++;
                    CGFloat width = MIN(size.width, self.config.maxLayoutWidth - lineLeft - lineRight);
                    view.frame = CGRectMake(lineLeft, CGRectGetMaxY(previousView.frame) + lineSpacing, width, size.height);
                    currentX = lineLeft + width;
                }
            }
            else {
                //第一次遍历，换行
                if(lineCount>=self.config.maxLine){
                    //行数超过限制
                    break;
                }
                lineCount ++;
                CGFloat width = MIN(size.width, self.config.maxLayoutWidth - lineLeft - lineRight);
                view.frame = CGRectMake(lineLeft, contentTop+lineTop, width, size.height);
                currentX += width;
            }
            previousView = view;
        }
    }
    else {
        //一行
        for (UIView *view in subviews) {
            CGSize size = view.intrinsicContentSize;
            //如果这里是固定宽度
            if (self.config.fixedItemWidth > 0) {
                size.width = self.config.fixedItemWidth;
            }
            if (size.width > self.config.maxLayoutWidth) {
                size.width = self.config.maxLayoutWidth;
            }
            view.frame = CGRectMake(currentX, contentTop+lineTop, size.width, size.height);
            currentX += size.width;
            currentX += itemSpacing;
            previousView = view;
        }
    }
    self.didSetup = YES;
}

//MARK: - 刷新数据
-(void)reloadData {
    //获取数据源
    if ([self.delegate respondsToSelector:@selector(hh_TagListViewDataSource:)]) {
        self.tags = [self.delegate hh_TagListViewDataSource:self];
    }
    [self removeAllTags];
    BCWeakObj(self);
    [self.tags enumerateObjectsUsingBlock:^(id<HHTagItemProtocol>  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        BCStrongObj(self);
        [self addTagModel:obj index:idx];
    }];
    [self layoutTags];
}

//MARK: - 选中标签、取消选中标签
- (void)selectTag:(id<HHTagItemProtocol> )tagModel {
    HHTagButton *findBtn = nil;
    for (HHTagButton *btn in self.allBtns) {
        if (btn.tagModel != nil && [btn.tagModel.uniqueId isEqualToNumber:tagModel.uniqueId]) {
            findBtn = btn;
            break;
        }
    }
    if (findBtn) {
        //手动选中
        [self onItemBtnClick:findBtn isGesture:NO];
    }
}
- (void)selectTagWithUniqueId:(NSNumber *)uniqueId {
    HHTagButton *findBtn = nil;
    for (HHTagButton *btn in self.allBtns) {
        if (btn.tagModel != nil && [btn.tagModel.uniqueId isEqualToNumber:uniqueId]) {
            findBtn = btn;
            break;
        }
    }
    if (findBtn) {
        //手动选中
        [self onItemBtnClick:findBtn isGesture:NO];
    }
}
- (void)deselectTag:(id<HHTagItemProtocol> )tagModel {
    HHTagButton *findBtn = nil;
    for (HHTagButton *btn in self.selectBtns) {
        if (btn.tagModel != nil && [btn.tagModel.uniqueId isEqualToNumber:tagModel.uniqueId]) {
            findBtn = btn;
            break;
        }
    }
    if (findBtn) {
        findBtn.selected = NO;
        [self.selectBtns removeObject:findBtn];
    }
}
- (void)deselectAllTags {
    //当前按钮排斥，则取消其他按钮
    [self.selectBtns enumerateObjectsUsingBlock:^(UIButton * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        obj.selected = NO;
    }];
    [self.selectBtns removeAllObjects];
}


//MARK: - private
/**
 添加tag

 @param tag tag description
 @param index index description
 */
- (void)addTagModel:(id<HHTagItemProtocol> )tag index:(NSUInteger)index {
    NSParameterAssert(tag);
    //生成tag
    HHTagButton *btnTag = [HHTagButton hh_allocWithTag:tag];
    [btnTag hh_loadWithConfig:self.config];
    [btnTag addTarget:self action:@selector(onItemBtnClick:) forControlEvents:UIControlEventTouchUpInside];
    [self addSubview:btnTag];
    [self.allBtns addObject:btnTag];
    if ([self.delegate respondsToSelector:@selector(hh_TagListView:willDisplayTag:)]) {
        [self.delegate hh_TagListView:self willDisplayTag:btnTag];
    }
    //是否需要要选中
    if (tag.selected) {
        //这里直接调用方法
//        btnTag.selected = YES;
        [self onItemBtnClick:btnTag isGesture:NO];
//        [btnTag sendActionsForControlEvents:UIControlEventTouchUpInside];
    }
    self.didSetup = NO;
    [self invalidateIntrinsicContentSize];
}


//MARK: - 移除标签
/**
 移除所有标签
 */
- (void)removeAllTags {
    [self.selectBtns removeAllObjects];
    [self.allBtns makeObjectsPerformSelector:@selector(removeFromSuperview)];
    [self.allBtns removeAllObjects];
    self.didSetup = NO;
    [self invalidateIntrinsicContentSize];
}

//MARK: - 计算size
-(CGSize)intrinsicContentSize {
    return [[self class] intrinsicContentSizeWithTags:self.tags withConfig:self.config];
}

+(CGSize )intrinsicContentSize:(NSArray<NSString *> *)texts withConfig:(HHTagListConfig *)config {
    if (texts.count<=0) {
        return CGSizeZero;
    }
    BOOL hasPreviousView = NO;//前面是否有view
    CGFloat contentTop = config.contentPadding.top;
    CGFloat contentBottom = config.contentPadding.bottom;
    CGFloat lineTop = config.linePadding.top;
    CGFloat lineBottom = config.linePadding.bottom;
    CGFloat lineLeft = config.contentPadding.left + config.linePadding.left;
    CGFloat lineRight = config.contentPadding.right + config.linePadding.right;
    CGFloat itemSpacing = config.rowSpacing;
    CGFloat lineSpacing = config.lineSpacing;
    CGFloat currentX = lineLeft;
    CGFloat intrinsicHeight = contentTop + contentBottom;
    CGFloat intrinsicWidth = lineLeft;
    if (config.maxLine>1 && config.maxLayoutWidth > 0) {//多行
        NSInteger lineCount = 0;
        for (NSString *tagText in texts) {
            //计算按钮size
            CGSize size = [HHTagButton intrinsicContentSize:tagText withConfig:config];
            //判断是否第一次遍历
            if (hasPreviousView) {
                //不是第一次遍历
                CGFloat width = size.width;
                currentX += itemSpacing;
                if (currentX + width + lineRight <= config.maxLayoutWidth) {
                    currentX += size.width;
                }
                else {
                    //换行
                    if(lineCount >= config.maxLine){
                        //行数超过限制
                        break;
                    }
                    lineCount ++;
                    currentX = lineLeft + size.width;
                    intrinsicHeight += lineTop + size.height + lineBottom;
                }
            }
            else {
                //第一次遍历，换行
                if(lineCount >= config.maxLine){
                    //行数超过限制
                    break;
                }
                lineCount ++;
                intrinsicHeight += lineTop + size.height+lineBottom;
                currentX += size.width;
            }
            hasPreviousView = YES;
            intrinsicWidth = MAX(intrinsicWidth, currentX + lineRight);
        }
        intrinsicHeight += lineSpacing * (lineCount - 1);
    }
    else {
        //只有一行
        CGSize size = CGSizeZero;
        for (NSString *tagText in texts) {
            size = [HHTagButton intrinsicContentSize:tagText withConfig:config];
            //如果这里是固定宽度
            if (config.fixedItemWidth>0) {
                size.width = config.fixedItemWidth;
            }
            intrinsicWidth += size.width;
        }
        intrinsicWidth += itemSpacing * (texts.count - 1) + lineRight;
        intrinsicHeight += lineTop + size.height + lineBottom;
    }
    return CGSizeMake(intrinsicWidth, intrinsicHeight);
}

+(CGSize )intrinsicContentSize:(NSArray<NSDictionary *> *)textDicts withBlock:(NSString *(^)(NSDictionary *textDict) )textBlock withConfig:(HHTagListConfig *)config {
    if (textDicts.count<=0) {
        return CGSizeZero;
    }
    if (!textBlock) {
        return CGSizeZero;
    }
    BOOL hasPreviousView = NO;//前面是否有view
    CGFloat contentTop = config.contentPadding.top;
    CGFloat contentBottom = config.contentPadding.bottom;
    CGFloat lineTop = config.linePadding.top;
    CGFloat lineBottom = config.linePadding.bottom;
    CGFloat lineLeft = config.contentPadding.left + config.linePadding.left;
    CGFloat lineRight = config.contentPadding.right + config.linePadding.right;
    CGFloat itemSpacing = config.rowSpacing;
    CGFloat lineSpacing = config.lineSpacing;
    CGFloat currentX = lineLeft;
    CGFloat intrinsicHeight = contentTop + contentBottom;
    CGFloat intrinsicWidth = lineLeft;
    
    if (config.maxLine>1 && config.maxLayoutWidth > 0) {//多行
        NSInteger lineCount = 0;
        for (NSDictionary *tagDict in textDicts) {
            NSString *tagText = textBlock(tagDict);
            //计算按钮size
            CGSize size = [HHTagButton intrinsicContentSize:tagText withConfig:config];
            //判断是否第一次遍历
            if (hasPreviousView) {
                //不是第一次遍历
                CGFloat width = size.width;
                currentX += itemSpacing;
                if (currentX + width + lineRight <= config.maxLayoutWidth) {
                    currentX += size.width;
                }
                else {
                    //换行
                    if(lineCount >= config.maxLine){
                        //行数超过限制
                        break;
                    }
                    lineCount ++;
                    currentX = lineLeft + size.width;
                    intrinsicHeight += lineTop+size.height+lineBottom;
                }
            }
            else {
                //第一次遍历，换行
                if(lineCount >= config.maxLine){
                    //行数超过限制
                    break;
                }
                lineCount ++;
                intrinsicHeight += lineTop+size.height+lineBottom;
                currentX += size.width;
            }
            hasPreviousView = YES;
            intrinsicWidth = MAX(intrinsicWidth, currentX + lineRight);
        }
        intrinsicHeight += lineSpacing * (lineCount - 1);
    }
    else {
        //只有一行
        CGSize size = CGSizeZero;
        for (NSDictionary *tagDict in textDicts) {
            NSString *tagText = textBlock(tagDict);
            size = [HHTagButton intrinsicContentSize:tagText withConfig:config];
            //如果这里是固定宽度
            if (config.fixedItemWidth>0) {
                size.width = config.fixedItemWidth;
            }
            intrinsicWidth += size.width;
        }
        intrinsicWidth += itemSpacing * (textDicts.count - 1) + lineRight;
        intrinsicHeight += lineTop + size.height + lineBottom;
    }
    return CGSizeMake(intrinsicWidth, intrinsicHeight);
}

+(CGSize )intrinsicContentSizeWithTags:(NSArray<id<HHTagItemProtocol> > *)tags withConfig:(HHTagListConfig *)config {
    if (tags.count<=0) {
        return CGSizeZero;
    }
    BOOL hasPreviousView = NO;//前面是否有view
    CGFloat contentTop = config.contentPadding.top;
    CGFloat contentBottom = config.contentPadding.bottom;
    CGFloat lineTop = config.linePadding.top;
    CGFloat lineBottom = config.linePadding.bottom;
    CGFloat lineLeft = config.contentPadding.left + config.linePadding.left;
    CGFloat lineRight = config.contentPadding.right + config.linePadding.right;
    CGFloat itemSpacing = config.rowSpacing;
    CGFloat lineSpacing = config.lineSpacing;
    CGFloat currentX = lineLeft;
    CGFloat intrinsicHeight = contentTop + contentBottom;
    CGFloat intrinsicWidth = lineLeft;
    
    if (config.maxLine>1 && config.maxLayoutWidth > 0) {
        //多行
        NSInteger lineCount = 0;
        for (id<HHTagItemProtocol> tagItem in tags) {
            //计算按钮size
            CGSize size = [HHTagButton intrinsicContentSize:tagItem.name withConfig:config];
            //判断是否第一次遍历
            if (hasPreviousView) {
                //不是第一次遍历
                CGFloat width = size.width;
                currentX += itemSpacing;
                if (currentX + width + lineRight <= config.maxLayoutWidth) {
                    currentX += size.width;
                }
                else {
                    //换行
                    if(lineCount >= config.maxLine){
                        //行数超过限制
                        break;
                    }
                    lineCount ++;
                    currentX = lineLeft + size.width;
                    intrinsicHeight +=  size.height;
                }
            }
            else {
                //第一次遍历，换行
                if(lineCount >= config.maxLine){
                    //行数超过限制
                    break;
                }
                lineCount ++;
                intrinsicHeight += lineTop + size.height + lineBottom;
                currentX += size.width;
            }
            hasPreviousView = YES;
            intrinsicWidth = MAX(intrinsicWidth, currentX + lineRight);
        }
        intrinsicHeight += lineSpacing * (lineCount - 1);
    }
    else {
        //只有一行
        CGSize size = CGSizeZero;
        for (id<HHTagItemProtocol> tagItem in tags) {
            size = [HHTagButton intrinsicContentSize:tagItem.name withConfig:config];
            //如果这里是固定宽度
            if (config.fixedItemWidth>0) {
                size.width = config.fixedItemWidth;
            }
            intrinsicWidth += size.width;
        }
        intrinsicWidth += itemSpacing * (tags.count - 1) + lineRight;
        intrinsicHeight += lineTop + size.height + lineBottom;
    }
    return CGSizeMake(intrinsicWidth, intrinsicHeight);
}

@end
